#include "GraphDbService.h"
#include "../../tools/DbClient/DbClient.h"
#include "../../tools/Neo4jValueConverter/Neo4jValueConverter.h"
#include <iostream> // 用于示例日志输出，可选
#include <grpcpp/grpcpp.h> // 确保包含 gRPC 状态码等
#include <neo4j-client.h>
#include <sstream>
#include <queue>
#include <unordered_map>
#include <regex>
#include <nlohmann/json.hpp>

using grpc::Status;
using grpc::StatusCode;
using json = nlohmann::json;

// 使用正则表达式提取 (:Label{ 中的 Label
std::string extract_label_from_neo4j_string(const std::string& input) {
    std::smatch match;
    
    // 正则：匹配 (: 开头，然后捕获标签名（字母数字下划线），然后是 {
    std::regex label_regex(R"xyz(\(\:([a-zA-Z_][a-zA-Z0-9_]*)\{)xyz");

    if (std::regex_search(input, match, label_regex) && match.size() > 1) {
        return match[1].str();  // 返回捕获的标签名
    }
    std::cout << "Extract error" << '\n';
    return "";  // 未找到
}


// 将节点类型的neo4j字符串转换为边类型的neo4j字符串
void convert_r_to_node_str(std::string& s) {

    // 匹配模式：-[:TYPE{props}]- 并替换为 (:TYPE{props})
    std::regex rel_pattern(R"xyz(-\[\:([a-zA-Z_][a-zA-Z0-9_]*)\{)xyz");
    
    // 替换开头：-\[:TYPE{  → (:TYPE{
    s = std::regex_replace(s, rel_pattern, "(:$1{");

    // 匹配结尾：}]- 并替换为 })
    std::regex tail_pattern(R"xyz(\}\]-*$)xyz");  // 允许末尾有换行或空格
    s = std::regex_replace(s, tail_pattern, "}");
}

std::string neo4j_nodeString_to_json(const std::string& input) {
    std::string s = input;

    // 1. 去掉开头的 (:Label{
    std::regex header_regex(R"xyz(\(\:[a-zA-Z_][a-zA-Z0-9_]*\{)xyz");
    s = std::regex_replace(s, header_regex, "{");

    // 2. 去掉结尾的 })
    std::regex footer_regex(R"xyz(\}\)$)xyz");
    s = std::regex_replace(s, footer_regex, "}");

    // 3. 给 key 加上双引号
    std::regex key_regex(R"xyz(\b([a-zA-Z_][a-zA-Z0-9_]*)\s*:)xyz");
    s = std::regex_replace(s, key_regex, "\"$1\":");

    return s;
}

// --- 推荐查询接口 ---

// 根据 List ID 获取相关子图
Status GraphDbService::GetSubgraphByListId(ServerContext* context, 
                                          const GetSubgraphByListIdRequest* request,
                                          GetSubgraphByListIdResponse* response) {
    // 从请求中解析参数
    int32_t list_id = request->list_id();
    
    // 检查可选的时间范围参数
    if (request->has_date_range()) {
        std::string start_date = request->date_range().start_date();
        std::string end_date = request->date_range().end_date();
    } 
    std::ostringstream cypher_oss;
    cypher_oss << "MATCH (parent_node {id: $id})-[r]->(son_node) "
               << "RETURN parent_node, r, son_node"; 
    const std::string cypher_query = cypher_oss.str();
    // 3. --- 初始化结果图 ---
    graph::GenericSubgraph res;  // ✅ 栈上对象，不要用 set_allocated

    std::queue<int32_t>q;
    std::unordered_map<int32_t, bool>st;
    std::unordered_map<int32_t, int>d;

    q.push(list_id);
    d[list_id] = 0;
    while(q.size()){
        int32_t current_id = q.front();
        q.pop();
        if(d[current_id] > 2)continue; // 不对过深的节点进行扩展

        // 构造参数
        neo4j_map_entry_t entries[] = {
            { .key = neo4j_string("id"), .value = neo4j_int(current_id) }
        };
        neo4j_value_t params = neo4j_map(entries, 1);
        // 执行查询
        DbClient& dbClient = DbClient::getInstance(); // 获取全局单例
        neo4j_result_stream_t* stream = dbClient.run(cypher_query.c_str(), params);
        if (stream == nullptr) {
            std::cerr << "neo4j_run failed for id=" << current_id << std::endl;
            continue;
        }
        neo4j_result_t* result;

        // 用于存储边相关的信息
        int32_t start_id = -1, end_id = -1;
        std::string start_label, end_label;
        std::string r_label;
        std::string r_property_json;
        while ((result = neo4j_fetch_next(stream)) != nullptr) {
            unsigned int nfields = neo4j_nfields(stream);
            if(nfields != 3)continue; // 不满足(父节点, 边, 子节点)的结构
            int32_t start_id, end_id; // 边的起始/终止节点的id
            std::string start_label, end_label; // 边的起始/终止节点的类型
            std::string r_type; // 边的类型
            std::string r_property_json; // 其他额外信息

            for (unsigned int i = 0; i < nfields; ++i) {
                const char* field_name = neo4j_fieldname(stream, i);
                neo4j_value_t field_value = neo4j_result_field(result, i);

                if (neo4j_is_null(field_value)) continue;

                const char* type_str = neo4j_typestr(neo4j_type(field_value));
                char buffer[4096];
                neo4j_tostring(field_value, buffer, sizeof(buffer));

                if (strcmp(type_str, "Node") == 0) {
                    std::string node_msg(buffer);
                    std::string json_msg = neo4j_nodeString_to_json(node_msg);
                    std::string label = extract_label_from_neo4j_string(node_msg);
                    json json_obj = json::parse(json_msg);

                    if(!json_obj.contains("id"))continue; // 如果不包含id字段, 是一个非法的点
                    int32_t id = json_obj["id"];

                    // 存储部分边的信息
                    if(i == 0){ // 第一个字段是父节点
                        start_id = id;
                        start_label = label;
                    }
                    else if(i ==2){ // 第三个字段是子节点
                        end_id = id;
                        end_label = label;
                    }

                    if(st[id])continue;
                    st[id] = 1; // 记录点已经入队
                    if(id != list_id){ // 初始节点id已经入队过了
                        q.push(id);
                        d[id] = d[current_id] + 1; // 记录点的深度
                    }

                    // 往答案中添加节点
                    auto* node = res.add_nodes();
                    node->set_id(id);
                    node->set_label(label);
                    node->set_properties_json(json_msg);

                }
                else{
                    std::string r_msg(buffer); // 用buffer中的字符串初始化边信息字符串
                    convert_r_to_node_str(r_msg); // 转为节点风格的字符串
                    r_property_json = neo4j_nodeString_to_json(r_msg);
                    r_label = extract_label_from_neo4j_string(r_msg);
                }
            }
            if(start_id != -1 && end_id != -1){ // 解析出了一条合法的边
                auto* r = res.add_relationships();
                r->set_type(r_label);
                r->set_start_node_id(start_id);
                r->set_start_node_label(start_label);
                r->set_end_node_id(end_id);
                r->set_end_node_label(end_label);
                r->set_properties_json(r_property_json);
            }
        }
        neo4j_close_results(stream);
    }

    // res是栈上的对象, 生命周期只存在于接口函数调用期间, 因此需要拷贝赋值给响应体
    *(response->mutable_subgraph()) = res; 
    
    // 设置响应结果
    response->set_success(true);
    
    return Status::OK;
}

// 根据 User ID 获取相关子图
Status GraphDbService::GetSubgraphByUserId(ServerContext* context,
                                          const GetSubgraphByUserIdRequest* request,
                                          GetSubgraphByUserIdResponse* response) {
    // 从请求中解析参数
    int32_t user_id = request->user_id();

    // std::cout << "Requesting subgraph for user_id: " << user_id << std::endl;
    
    // 构造 Cypher 查询语句 - 查找与用户相关的节点
    std::ostringstream cypher_oss;
    cypher_oss << "MATCH (parent_node {id: $id})-[r]->(son_node) "
               << "RETURN parent_node, r, son_node"; 
    const std::string cypher_query = cypher_oss.str();
    
    // 3. --- 初始化结果图 ---
    graph::GenericSubgraph res;  // ✅ 栈上对象，不要用 set_allocated

    std::queue<int32_t> q;
    std::unordered_map<int32_t, bool> st;
    std::unordered_map<int32_t, int> d;

    q.push(user_id);
    d[user_id] = 0;
    
    while (!q.empty()) {
        int32_t current_id = q.front();
        q.pop();
        
        if (d[current_id] > 2) continue; // 不对过深的节点进行扩展

        // 构造参数
        neo4j_map_entry_t entries[] = {
            { .key = neo4j_string("id"), .value = neo4j_int(current_id) }
        };
        neo4j_value_t params = neo4j_map(entries, 1);
        
        // 执行查询
        DbClient& dbClient = DbClient::getInstance(); // 获取全局单例
        neo4j_result_stream_t* stream = dbClient.run(cypher_query.c_str(), params);
        if (stream == nullptr) {
            std::cerr << "neo4j_run failed for id=" << current_id << std::endl;
            continue;
        }
        
        neo4j_result_t* result;

        // 用于存储边相关的信息
        int32_t start_id = -1, end_id = -1;
        std::string start_label, end_label;
        std::string r_label;
        std::string r_property_json;
        
        while ((result = neo4j_fetch_next(stream)) != nullptr) {
            unsigned int nfields = neo4j_nfields(stream);
            if (nfields != 3) continue; // 不满足(父节点, 边, 子节点)的结构
            
            start_id = -1;
            end_id = -1;
            start_label.clear();
            end_label.clear();
            r_label.clear();
            r_property_json.clear();

            for (unsigned int i = 0; i < nfields; ++i) {
                const char* field_name = neo4j_fieldname(stream, i);
                neo4j_value_t field_value = neo4j_result_field(result, i);

                if (neo4j_is_null(field_value)) continue;

                const char* type_str = neo4j_typestr(neo4j_type(field_value));
                char buffer[4096];
                neo4j_tostring(field_value, buffer, sizeof(buffer));

                if (strcmp(type_str, "Node") == 0) {
                    std::string node_msg(buffer);
                    std::string json_msg = neo4j_nodeString_to_json(node_msg);
                    std::string label = extract_label_from_neo4j_string(node_msg);
                    json json_obj = json::parse(json_msg);

                    if (!json_obj.contains("id")) continue; // 如果不包含id字段, 是一个非法的点
                    int32_t id = json_obj["id"];

                    // 存储部分边的信息
                    if (i == 0) { // 第一个字段是父节点
                        start_id = id;
                        start_label = label;
                    }
                    else if (i == 2) { // 第三个字段是子节点
                        end_id = id;
                        end_label = label;
                    }

                    if (st[id]) continue;
                    st[id] = true; // 记录点已经访问过
                    if (id != user_id) { // 初始节点id已经访问过了
                        q.push(id);
                        d[id] = d[current_id] + 1; // 记录点的深度
                    }

                    // 往答案中添加节点
                    auto* node = res.add_nodes();
                    node->set_id(id);
                    node->set_label(label);
                    node->set_properties_json(json_msg);
                }
                else {
                    std::string r_msg(buffer); // 用buffer中的字符串初始化边信息字符串
                    convert_r_to_node_str(r_msg); // 转为节点风格的字符串
                    r_property_json = neo4j_nodeString_to_json(r_msg);
                    r_label = extract_label_from_neo4j_string(r_msg);
                }
            }
            
            if (start_id != -1 && end_id != -1) { // 解析出了一条合法的边
                auto* r = res.add_relationships();
                r->set_type(r_label);
                r->set_start_node_id(start_id);
                r->set_start_node_label(start_label);
                r->set_end_node_id(end_id);
                r->set_end_node_label(end_label);
                r->set_properties_json(r_property_json);
            }
        }
        neo4j_close_results(stream);
    }

    // res是栈上的对象, 生命周期只存在于接口函数调用期间, 因此需要拷贝赋值给响应体
    *(response->mutable_subgraph()) = res; 
    
    // 设置响应结果
    response->set_success(true);
    
    return Status::OK;
}

void printNeo4jMap(neo4j_value_t map_value) {
    if (neo4j_type(map_value) != NEO4J_MAP) {
        printf("Value is not a map\n");
        return;
    }
    
    int n_entries = neo4j_map_size(map_value);
    printf("Map contains %d entries:\n", n_entries);
    
    for (int i = 0; i < n_entries; i++) {
        const neo4j_map_entry_t *entry = neo4j_map_getentry(map_value, i);
        if (entry != NULL) {
            // 打印键
            char key_buffer[256];
            neo4j_tostring(entry->key, key_buffer, sizeof(key_buffer));
            printf("  Key: %s, ", key_buffer);
            
            // 打印值
            char value_buffer[512];
            neo4j_tostring(entry->value, value_buffer, sizeof(value_buffer));
            printf("Value: %s\n", value_buffer);
        }
    }
}

void printProtoNeo4jMap(const graph::Neo4jMap& map) {
    std::cout << "Neo4jMap contains " << map.fields_size() << " entries:" << std::endl;
    
    for (const auto& [key, value] : map.fields()) {
        std::cout << "  Key: " << key << ", ";
        
        // 根据 oneof 类型打印值
        switch (value.value_case()) {
            case graph::Neo4jValue::kStringValue:
                std::cout << "Value: " << value.string_value() << " (string)" << std::endl;
                break;
            case graph::Neo4jValue::kIntValue:
                std::cout << "Value: " << value.int_value() << " (int)" << std::endl;
                break;
            case graph::Neo4jValue::kFloatValue:
                std::cout << "Value: " << value.float_value() << " (float)" << std::endl;
                break;
            case graph::Neo4jValue::kBoolValue:
                std::cout << "Value: " << (value.bool_value() ? "true" : "false") << " (bool)" << std::endl;
                break;
            case graph::Neo4jValue::kNullValue:
                std::cout << "Value: null (null)" << std::endl;
                break;
            case graph::Neo4jValue::kListValue:
                std::cout << "Value: [list with " << value.list_value().values_size() << " items] (list)" << std::endl;
                break;
            case graph::Neo4jValue::kMapValue:
                std::cout << "Value: [nested map with " << value.map_value().fields_size() << " entries] (map)" << std::endl;
                // 如果需要打印嵌套的 map，可以递归调用
                // printProtoNeo4jMap(value.map_value());
                break;
            default:
                std::cout << "Value: <unknown type>" << std::endl;
                break;
        }
    }
}

Status GraphDbService::Neo4jRun(ServerContext* context,
                               const Neo4jRunRequest* request,
                               Neo4jRunResponse* response) {
    try {
        std::string cypher = request->cypher();

        graph::Neo4jMap params_map = request->parameters();
        std::vector<std::string> keys;
        std::vector<graph::Neo4jValue> values;
        // 遍历 map 中的所有键值对
        std::vector<neo4j_map_entry_t> entries;
        for (const auto& field : params_map.fields()) {
            keys.push_back(field.first);    // 提取键
            values.push_back(field.second); // 提取值
        } 
        for(int i = 0; i < keys.size(); i++){
            const std::string& key_ref = keys[i];
            neo4j_value_t neo4j_val = Neo4jValueConverter::toNeo4jValue(values[i]);
            entries.push_back({ 
                .key = neo4j_string(key_ref.c_str()), 
                .value = neo4j_val 
            });
        }
        neo4j_value_t params = neo4j_map(entries.data(), entries.size());
        
        // 执行查询
        DbClient& dbClient = DbClient::getInstance();
        neo4j_result_stream_t* stream = dbClient.run(cypher.c_str(), params);
        if (stream == nullptr) {
            response->set_success(false);
            response->set_error_message("Failed to execute query");
            return Status::OK;
        }
        
        // 消费流式结果并构建响应
        CypherResult* result = response->mutable_result();
        neo4j_result_t* result_item;
        
        // 获取字段名
        unsigned int nfields = neo4j_nfields(stream);
        std::vector<std::string> field_names;
        for (unsigned int i = 0; i < nfields; ++i) {
            const char* field_name = neo4j_fieldname(stream, i);
            field_names.push_back(std::string(field_name));
        }
        
        int64_t row_count = 0;
        while ((result_item = neo4j_fetch_next(stream)) != nullptr) {
            QueryResultRow* row = result->add_rows();
            
            // 设置字段名（只需要设置一次）
            if (row_count == 0) {
                for (const auto& name : field_names) {
                    row->add_field_names(name);
                }
            }
            
            // 处理每一列的值
            for (unsigned int i = 0; i < nfields; ++i) {
                neo4j_value_t field_value = neo4j_result_field(result_item, i);
                
                if (neo4j_is_null(field_value)) {
                    row->add_field_values("null");
                    row->add_field_types("NULL");
                } else {
                    const char* type_str = neo4j_typestr(neo4j_type(field_value));
                    std::string value_str = Neo4jValueConverter::toString(field_value);
                    
                    row->add_field_values(value_str);
                    row->add_field_types(std::string(type_str));
                }
            }
            row_count++;
        }
        
        neo4j_close_results(stream);
        
        result->set_total_count(row_count);
        result->set_has_records(row_count > 0);
        response->set_success(true);
        
    } catch (const std::exception& e) {
        response->set_success(false);
        response->set_error_message(e.what());
    }
    
    return Status::OK;
}